home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 42 / Amiga Format AFCD42 (Issue 126, Aug 1999).iso / -serious- / programming / other / jikes / src / incrmnt.cpp < prev    next >
C/C++ Source or Header  |  1999-05-14  |  15KB  |  410 lines

  1. // $Id: incrmnt.cpp,v 1.6 1999/03/10 19:59:21 shields Exp $
  2. //
  3. // This software is subject to the terms of the IBM Jikes Compiler
  4. // License Agreement available at the following URL:
  5. // http://www.ibm.com/research/jikes.
  6. // Copyright (C) 1996, 1998, International Business Machines Corporation
  7. // and others.  All Rights Reserved.
  8. // You must accept the terms of that agreement to use this software.
  9. //
  10. #include "config.h"
  11. #include <sys/stat.h>
  12. #include <iostream.h>
  13. #include "bool.h"
  14. #include "control.h"
  15. #include "scanner.h"
  16. #include "parser.h"
  17. #include "semantic.h"
  18. #include "unicode.h"
  19. #include "set.h"
  20.  
  21. void Control::RemoveTrashedTypes(SymbolSet &type_trash_set)
  22. {
  23.     TypeSymbol *type;
  24.  
  25.     //
  26.     // For each type T that is going to be trashed, and for each parent P of T that
  27.     // is not itself being trashed, remove T from the set of dependents of P.
  28.     // If T is a subtype of P it is also removed from the subtypes set.
  29.     //
  30.     for (type = (TypeSymbol *) type_trash_set.FirstElement(); type; type = (TypeSymbol *) type_trash_set.NextElement())
  31.     {
  32.         for (TypeSymbol *parent = (TypeSymbol *) type -> parents -> FirstElement();
  33.                          parent;
  34.                          parent = (TypeSymbol *) type -> parents -> NextElement())
  35.         {
  36.             if (! type_trash_set.IsElement(parent))
  37.             {
  38.                 parent -> dependents -> RemoveElement(type);
  39.                 parent -> subtypes -> RemoveElement(type);
  40.             }
  41.         }
  42.     }
  43.  
  44.     //
  45.     // We can now safely delete the type.
  46.     //
  47.     for (type = (TypeSymbol *) type_trash_set.FirstElement(); type; type = (TypeSymbol *) type_trash_set.NextElement())
  48.     {
  49.         PackageSymbol *package = type -> ContainingPackage();
  50.  
  51.         //
  52.         // If a type that is about to be trashed was read in via a class file, remove the class file.
  53.         // Note that invoking RemoveElement for a file that it does not contain has no ill effect.
  54.         //
  55.         FileSymbol *file_symbol = type -> file_symbol;
  56.         if (file_symbol && type -> Identity() == file_symbol -> Identity())
  57.             input_class_file_set.RemoveElement(file_symbol);
  58.  
  59.         //
  60.         // If a type that is about to be trashed was contained in the unnamed_package,
  61.         // remove it from the set "unnamed_package_types"
  62.         //
  63.         if (package == unnamed_package)
  64.             unnamed_package_types.RemoveElement(type);
  65.  
  66.         //
  67.         // Remove the type from its containing package.
  68.         //
  69.         package -> DeleteTypeSymbol(type);
  70.     }
  71.  
  72.     return;
  73. }
  74.  
  75.  
  76. inline DirectoryEntry *Control::FindInputFile(FileSymbol *file_symbol)
  77. {
  78.     int length = file_symbol -> Utf8NameLength() + FileSymbol::java_suffix_length;
  79.  
  80.     char *java_name = new char[length + 1]; // +1 for '\0'
  81.     strcpy(java_name, file_symbol -> Utf8Name());
  82.     strcat(java_name, FileSymbol::java_suffix);
  83.  
  84.     DirectoryEntry *java_entry = file_symbol -> directory_symbol -> FindEntry(java_name, length);
  85.  
  86.     delete [] java_name;
  87.  
  88.     return java_entry;
  89.  
  90. }
  91.  
  92.  
  93. //
  94. // For each file whose associated source (".java") has changed, add it to the list to be recompiled...
  95. //
  96. void Control::FindMoreRecentInputFiles(SymbolSet &file_candidates)
  97. {
  98.     for (FileSymbol *file_symbol = (FileSymbol *) file_candidates.FirstElement();
  99.                      file_symbol;
  100.                      file_symbol = (FileSymbol *) file_candidates.NextElement())
  101.     {
  102.         //
  103.         // If the type is not zipped and it is not already contained in the recompilation set, then check it...
  104.         //
  105.         if ((! file_symbol -> IsZip()) &&
  106.             (! recompilation_file_set.IsElement(file_symbol)) &&
  107.             (! expired_file_set.IsElement(file_symbol)))
  108.         {
  109.             //
  110.             // If there is no java source file or its time stamp is not newer than file_symbol then
  111.             // reset file_symbol to NULL. Otherwise, reset file symbol to the newer file.
  112.             //
  113.             DirectoryEntry *java_entry = FindInputFile(file_symbol);
  114.             if (! java_entry)
  115.             {
  116.                 if (file_symbol -> IsJava()) // A source file that was compiled in the previous pass no longer exists.
  117.                     expired_file_set.AddElement(file_symbol);
  118.             }
  119.             else if (java_entry -> Mtime() > file_symbol -> mtime) // a newer file was found
  120.             {
  121.                  file_symbol -> mtime = java_entry -> Mtime();
  122.                  recompilation_file_set.AddElement(file_symbol);
  123.             }
  124.         }
  125.     }
  126.  
  127.     return;
  128. }
  129.  
  130.  
  131. void Control::RereadDirectory(DirectorySymbol *directory_symbol)
  132. {
  133.     directory_symbol -> ResetDirectory();
  134.  
  135.     for (int i = 0; i < directory_symbol -> subdirectories.Length(); i++)
  136.         RereadDirectory(directory_symbol -> subdirectories[i]);
  137.  
  138.     return;
  139. }
  140.  
  141.  
  142. void Control::RereadDirectories()
  143. {
  144.     for (int i = (dot_classpath_index == 0 ? 0 : 1); i < classpath.Length(); i++)
  145.     {
  146.         PathSymbol *path_symbol = classpath[i];
  147.         if (! path_symbol -> IsZip())
  148.             RereadDirectory(path_symbol -> RootDirectory());
  149.     }
  150.  
  151.     return;
  152. }
  153.  
  154.  
  155. void Control::ComputeRecompilationSet(TypeDependenceChecker &dependence_checker)
  156. {
  157.     SymbolSet type_trash_set;
  158.  
  159.     //
  160.     // Find out if any source files has been touched since the last compilation and
  161.     // add all such files to recompilation_file_set.
  162.     //
  163.     FindMoreRecentInputFiles(dependence_checker.file_set);
  164.  
  165.     //
  166.     // Before messing with the files, compute a list of all the types that have just been compiled.
  167.     // We need to do this here as we will be "Resetting" and "reScanning" some files in the loop below,
  168.     // which in effect removes the set of types to which they were associated in the previous compilation.
  169.     //
  170.     int length_estimate = input_java_file_set.Size(); // an estimate of the size of the problem
  171.     Tuple<TypeSymbol *> input_types(length_estimate * 2);
  172.     for (FileSymbol *file_symbol = (FileSymbol *) input_java_file_set.FirstElement();
  173.                      file_symbol;
  174.                      file_symbol = (FileSymbol *) input_java_file_set.NextElement())
  175.     {
  176.         for (int i = 0; i < file_symbol -> types.Length(); i++)
  177.             input_types.Next() = file_symbol -> types[i];
  178.     }
  179.  
  180.     //
  181.     // Declare the closure set, and initialize it with the Union over the closure of the 
  182.     // types in the trash_bin. Essentially, we want to catch all "compiled" types in the
  183.     // compilation that has a dependence on these bad types.
  184.     //
  185.     SymbolSet dependents_closure(length_estimate);
  186.     for (int i = 0; i < type_trash_bin.Length(); i++)
  187.     {
  188.         TypeSymbol *type = type_trash_bin[i];
  189.         if (! dependents_closure.IsElement(type))
  190.         {
  191.             if (type -> dependents_closure)
  192.                  dependents_closure.Union(*(type -> dependents_closure));
  193.             else dependents_closure.AddElement(type);
  194.         }
  195.     }
  196.  
  197.     //
  198.     // Compute the set of types from the recompilation set that needs to be recompiled
  199.     // and update the recompilation file set.
  200.     //
  201.     SymbolSet new_set(length_estimate),
  202.               file_seen(length_estimate);
  203.     new_set = recompilation_file_set;
  204.     new_set.Union(expired_file_set);
  205.     file_seen = new_set;
  206.  
  207.     StoragePool *ast_pool = new StoragePool(64); // how much space do we need for a package declaration? estimate 64 tokens.
  208.  
  209.     //
  210.     // As long as there is a new_set of files to process,...
  211.     //
  212.     do
  213.     {
  214.         //
  215.         // For each file in new_set, compute the reflexive transitive closure of all types contained in that file.
  216.         // Next, reset and rescan the file. If the scan was successful, iterate over the new list of types to see
  217.         // if any of them had already been introduced in the previous compilation via a class file. If so, add all such
  218.         // types to the dependents closure.
  219.         //
  220.         for (FileSymbol *file_symbol = (FileSymbol *) new_set.FirstElement();
  221.                          file_symbol;
  222.                          file_symbol = (FileSymbol *) new_set.NextElement())
  223.         {
  224.             for (int i = 0; i < file_symbol -> types.Length(); i++)
  225.             {
  226.                 TypeSymbol *type = file_symbol -> types[